package com.leyou.test1.Demo2;

import org.apache.tomcat.util.threads.ThreadPoolExecutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

public class ThreadPools {
    //线程池的构造方法之一
    //public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
    //            BlockingQueue<Runnable> workQueue);
    //corePoolSize 线程池核心线程大小
    //maximumPoolSize.最大可扩展线程
    //keepAliveTime 存活时间
    /*表示线程没有任务执行时最多保持多久时间会终止。默认情况下，只有当线程池中的线程数大于corePoolSize时，
    keepAliveTime才会起作用，直到线程池中的线程数不大于corePoolSize，即当线程池中的线程数大于corePoolSize时，
    如果一个线程空闲的时间达到keepAliveTime，则会终止，直到线程池中的线程数不超过corePoolSize。
    但是如果调用了allowCoreThreadTimeOut(boolean)方法，在线程池中的线程数不大于corePoolSize时，
    keepAliveTime参数也会起作用，直到线程池中的线程数为0；*/
//    unit 时间单位

    public static void main(String[] args) {
        //一般使用静态方法创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(5));

        for(int i=0;i<15;i++){
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("线程池中线程数目："+executor.getPoolSize()+"，队列中等待执行的任务数目："+
                    executor.getQueue().size()+"，已执行玩别的任务数目："+executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
}


class MyTask implements Runnable {
    private int taskNum;

    public MyTask(int num) {
        this.taskNum = num;
    }

    @Override
    public void run() {
        System.out.println("正在执行task "+taskNum);
        try {
            Thread.currentThread().sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task "+taskNum+"执行完毕");
    }

    //线程池创建后,并不会创建线程,当执行任务时才会创建线程

    /*　从执行结果可以看出，当任务数目大于5时，便将任务放入任务缓存队列里面，
    当任务缓存队列满了之后，便创建新的线程。如果上面程序中，将for循环中改成执行20个任务，就会抛出任务拒绝异常了。*/
    //解释: 当任务数量大于核心线程数,任务就会放入队列中等待,当任务队列中放满时,就会临时创建线程(maximumPoolSize),
//    任务执行先后顺序:核心线程任务>扩展线程任务>任务队列(一旦放入任务队列,则执行顺序在扩展线程任务之后)
    //当扩展线程满时,且任务队列也满时则会抛异常(具体有4种策略)
    /*ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
        ThreadPoolExecutor.DiscardPolicy：也是丢弃任务，但是不抛出异常。
        ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
        ThreadPoolExecutor.CallerRunsPolicy：由调用线程处理该任务 */
}
